package com.linsen.erp.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.linsen.core.common.context.TokenContextHolder;
import com.linsen.core.common.enums.DeleteType;
import com.linsen.core.common.exception.BaseException;
import com.linsen.core.common.model.User;
import com.linsen.core.common.util.ConvertUtil;
import com.linsen.core.mybatisplus.extension.SqlFilter;
import com.linsen.core.redis.util.RedisSecurityUtil;
import com.linsen.erp.admin.entity.EmployeeEntity;
import com.linsen.erp.admin.entity.UserEntity;
import com.linsen.erp.admin.mapper.EmployeeMapper;
import com.linsen.erp.admin.provider.dto.EmployeeDTO;
import com.linsen.erp.admin.provider.qo.EmployeeQo;
import com.linsen.erp.admin.provider.vo.EmployeeVO;
import com.linsen.erp.admin.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 员工-基本信息 服务实现类
 * </p>
 *
 * @author zhaoyong
 * @since 2024-10-08
 */
@Service
@RequiredArgsConstructor
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, EmployeeEntity> implements IEmployeeService {

    private final SqlFilter sqlFilter;
    private final RedisSecurityUtil redisSecurityUtil;

    private IDeptService iDeptService;
    @Autowired
    public void setiDeptService(IDeptService iDeptService){
        this.iDeptService = iDeptService;
    }

    private IUserService iUserService;
    @Autowired
    public void setiUserService(IUserService iUserService){
        this.iUserService = iUserService;
    }

    private IEmployeeContactService iEmployeeContactService;
    @Autowired
    public void setiEmployeeContactService(IEmployeeContactService iEmployeeContactService){
        this.iEmployeeContactService = iEmployeeContactService;
    }

    private IEmployeeAccountService iEmployeeAccountService;
    @Autowired
    public void setiEmployeeAccountService(IEmployeeAccountService iEmployeeAccountService){
        this.iEmployeeAccountService = iEmployeeAccountService;
    }

    private IEmployeeEducationService iEmployeeEducationService;
    @Autowired
    public void setiEmployeeEducationService(IEmployeeEducationService iEmployeeEducationService){
        this.iEmployeeEducationService = iEmployeeEducationService;
    }

    private IEmployeeEmploymentService iEmployeeEmploymentService;
    @Autowired
    public void setiEmployeeEmploymentService(IEmployeeEmploymentService iEmployeeEmploymentService){
        this.iEmployeeEmploymentService = iEmployeeEmploymentService;
    }

    private IEmployeeReportingService iEmployeeReportingService;
    @Autowired
    public void setiEmployeeReportingService(IEmployeeReportingService iEmployeeReportingService){
        this.iEmployeeReportingService = iEmployeeReportingService;
    }

    /** 封装分页列表查询的wrapper对象 */
    private Wrapper<EmployeeEntity> getWrapper(EmployeeQo employeeQo){
        String no = employeeQo.getNo();
        String name = employeeQo.getName();
        Integer gender = employeeQo.getGender();
        String tel = employeeQo.getTel();
        String idcard = employeeQo.getIdcard();
        LocalDate startBirthday = employeeQo.getStartBirthday();
        LocalDate endBirthday = employeeQo.getEndBirthday();
        String address = employeeQo.getAddress();
        Integer registerType = employeeQo.getRegisterType();
        String nation = employeeQo.getNation();
        Integer marital = employeeQo.getMarital();
        String deptid = employeeQo.getDeptid();
        String appScope = employeeQo.getAppScope();

        String permissionSql = sqlFilter.getPermissionSql();

        return new LambdaQueryWrapper<EmployeeEntity>()
                .like(ObjectUtil.isNotEmpty(no),EmployeeEntity::getNo,no)
                .like(ObjectUtil.isNotEmpty(name),EmployeeEntity::getName,name)
                .eq(ObjectUtil.isNotNull(gender),EmployeeEntity::getGender, gender)
                .like(ObjectUtil.isNotEmpty(tel),EmployeeEntity::getTel,tel)
                .like(ObjectUtil.isNotEmpty(idcard),EmployeeEntity::getIdcard,idcard)
                .ge(ObjectUtil.isNotNull(startBirthday),EmployeeEntity::getBirthday,startBirthday)
                .le(ObjectUtil.isNotNull(endBirthday),EmployeeEntity::getBirthday,endBirthday)
                .like(ObjectUtil.isNotEmpty(address),EmployeeEntity::getAddress,address)
                .eq(ObjectUtil.isNotNull(registerType),EmployeeEntity::getRegisterType, registerType)
                .like(ObjectUtil.isNotEmpty(nation),EmployeeEntity::getNation,nation)
                .eq(ObjectUtil.isNotNull(marital),EmployeeEntity::getMarital, marital)
                .in(ObjectUtil.isNotEmpty(deptid),EmployeeEntity::getDeptid, iDeptService.getSubDeptidList(deptid))
                .like(ObjectUtil.isNotEmpty(appScope),EmployeeEntity::getAppScope,appScope)
                .eq(EmployeeEntity::getIsDeleted, DeleteType.NORMAL.getValue())
                .apply(ObjectUtil.isNotEmpty(permissionSql),permissionSql)
                .orderByDesc(EmployeeEntity::getCreateTime)
                ;
    }

    @Override
    public Page<EmployeeVO> page(EmployeeQo qo) {
        Page<EmployeeEntity> page = this.page(new Page<>(qo.getCurrent(), qo.getSize()), getWrapper(qo));

        Page<EmployeeVO> employeeVOPage = new Page<>(qo.getCurrent(), qo.getSize());
        employeeVOPage.setTotal(page.getTotal());

        List<EmployeeVO> employeeVOList = new ArrayList<>();
        page.getRecords().forEach(employeeEntity -> {
            EmployeeVO employeeVO = ConvertUtil.convert(employeeEntity, EmployeeVO.class);
            String id = employeeVO.getId();

            employeeVO.setUserVO(iUserService.get(employeeVO.getUserId()));
            employeeVO.setAreaDeptVO(iDeptService.get(employeeVO.getAreaDeptid()));
            employeeVO.setCompanyDeptVO(iDeptService.get(employeeVO.getCompanyDeptid()));
            employeeVO.setDeptVO(iDeptService.get(employeeVO.getDeptid()));
            employeeVO.setEmployeeAccountVO(iEmployeeAccountService.getByEmployeeId(id));
            employeeVO.setEmployeeContactVOList(iEmployeeContactService.listByEmployeeId(id));
            employeeVO.setEmployeeEducationVO(iEmployeeEducationService.getByEmployeeId(id));
            employeeVO.setEmployeeEmploymentVO(iEmployeeEmploymentService.getByEmployeeId(id));
            employeeVO.setEmployeeReportingVO(iEmployeeReportingService.getByEmployeeId(id));

            employeeVOList.add(employeeVO);
        });
        employeeVOPage.setRecords(employeeVOList);

        return employeeVOPage;
    }

    @Override
    public EmployeeVO get(String id) {
        EmployeeVO employeeVO = ConvertUtil.convert(this.getById(id), EmployeeVO.class);

        employeeVO.setUserVO(iUserService.get(employeeVO.getUserId()));
        employeeVO.setAreaDeptVO(iDeptService.get(employeeVO.getAreaDeptid()));
        employeeVO.setCompanyDeptVO(iDeptService.get(employeeVO.getCompanyDeptid()));
        employeeVO.setDeptVO(iDeptService.get(employeeVO.getDeptid()));
        employeeVO.setEmployeeAccountVO(iEmployeeAccountService.getByEmployeeId(id));
        employeeVO.setEmployeeContactVOList(iEmployeeContactService.listByEmployeeId(id));
        employeeVO.setEmployeeEducationVO(iEmployeeEducationService.getByEmployeeId(id));
        employeeVO.setEmployeeEmploymentVO(iEmployeeEmploymentService.getByEmployeeId(id));
        employeeVO.setEmployeeReportingVO(iEmployeeReportingService.getByEmployeeId(id));

        return employeeVO;
    }

    @Transactional
    @Override
    public void saveEmployee(EmployeeDTO employeeDTO) {
        User user = this.redisSecurityUtil.getUser(TokenContextHolder.getToken());
        String deptId = user.getDeptId();
        String userid = user.getUserid();
        String username = user.getUsername();

        //判定工号是否唯一
        String no = employeeDTO.getNo();

        long count = this.count(
                new LambdaQueryWrapper<EmployeeEntity>()
                        .eq(EmployeeEntity::getNo, no)
                        .eq(EmployeeEntity::getIsDeleted, DeleteType.NORMAL.getValue())
        );
        if (count > 0){
            throw new BaseException("工号不能重复");
        }

        EmployeeEntity employeeEntity = ConvertUtil.convert(employeeDTO, EmployeeEntity.class);
        employeeEntity.setGeneratorDeptid(deptId);
        employeeEntity.setGeneratorUserid(userid);

        //查询部门对应的区域、公司信息
        String deptid = employeeDTO.getDeptid();
        if (ObjectUtil.isEmpty(deptid)){
            throw new BaseException("所选部门不存在");
        }
        employeeEntity.setAreaDeptid(iDeptService.getParentAreaByDeptId(deptid));
        employeeEntity.setCompanyDeptid(iDeptService.getParentCompanyByDeptId(deptid));

        this.save(employeeEntity);
        String id = employeeEntity.getId();

        //设置账户信息
        iEmployeeAccountService.set(id,employeeDTO.getEmployeeAccountDTO());
        //设置紧急联系人
        iEmployeeContactService.set(id,employeeDTO.getEmployeeContactDTOList());
        //设置教育信息
        iEmployeeEducationService.set(id,employeeDTO.getEmployeeEducationDTO());
        //设置用工信息
        iEmployeeEmploymentService.set(id,employeeDTO.getEmployeeEmploymentDTO());
        //设置汇报关系
        iEmployeeReportingService.set(id,employeeDTO.getEmployeeReportingDTO());

        //创建登录账户
        UserEntity userEntity = iUserService.createByEmployee(employeeDTO);
        employeeEntity.setUserId(userEntity.getId());
        employeeEntity.setUsername(userEntity.getUsername());
        this.updateById(employeeEntity);
    }

    @Transactional
    @Override
    public void updateEmployee(EmployeeDTO employeeDTO) {
        //判定工号是否唯一
        String id = employeeDTO.getId();
        String no = employeeDTO.getNo();

        long count = this.count(
                new LambdaQueryWrapper<EmployeeEntity>()
                        .ne(EmployeeEntity::getId,id)
                        .eq(EmployeeEntity::getNo, no)
                        .eq(EmployeeEntity::getIsDeleted, DeleteType.NORMAL.getValue())
        );
        if (count > 0){
            throw new BaseException("工号不能重复");
        }

        EmployeeEntity employeeEntity = ConvertUtil.convert(employeeDTO, EmployeeEntity.class);

        //查询部门对应的区域、公司信息
        String deptid = employeeDTO.getDeptid();
        if (ObjectUtil.isEmpty(deptid)){
            throw new BaseException("所选部门不存在");
        }
        employeeEntity.setAreaDeptid(iDeptService.getParentAreaByDeptId(deptid));
        employeeEntity.setCompanyDeptid(iDeptService.getParentCompanyByDeptId(deptid));

        this.updateById(employeeEntity);

        //设置账户信息
        iEmployeeAccountService.set(id,employeeDTO.getEmployeeAccountDTO());
        //设置紧急联系人
        iEmployeeContactService.set(id,employeeDTO.getEmployeeContactDTOList());
        //设置教育信息
        iEmployeeEducationService.set(id,employeeDTO.getEmployeeEducationDTO());
        //设置用工信息
        iEmployeeEmploymentService.set(id,employeeDTO.getEmployeeEmploymentDTO());
        //设置汇报关系
        iEmployeeReportingService.set(id,employeeDTO.getEmployeeReportingDTO());
    }

    @Transactional
    @Override
    public void delete(String id) {
        this.update(
                new UpdateWrapper<EmployeeEntity>().lambda()
                        .set(EmployeeEntity::getIsDeleted,DeleteType.DELETED.getValue())
                        .eq(EmployeeEntity::getId,id)
        );
    }
}
